package com.wt.admin.service.language.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.aizuda.easy.security.code.BasicCode;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.wt.admin.code.language.Tagging2100;
import com.wt.admin.domain.dto.language.SentenceDTO;
import com.wt.admin.domain.dto.language.SentenceKeywordMapperDTO;
import com.wt.admin.domain.entity.language.KeywordsEntity;
import com.wt.admin.domain.entity.language.SentenceEntity;
import com.wt.admin.domain.entity.sys.SysOperationLogEntity;
import com.wt.admin.domain.vo.language.ClassificationVO;
import com.wt.admin.domain.vo.language.QAVO;
import com.wt.admin.domain.vo.language.SentenceVO;
import com.wt.admin.mapper.language.SentenceMapper;
import com.wt.admin.mapper.sys.SysOperationLogMapper;
import com.wt.admin.service.language.TaggingService;
import com.wt.admin.util.AssertUtil;
import com.wt.admin.util.PageUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import jakarta.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
public class TaggingServiceImpl extends ServiceImpl<SentenceMapper, SentenceEntity> implements TaggingService {

    @Resource
    private SentenceMapper sentenceMapper;

    @Override
    public SentenceVO add(SentenceDTO data) {
        AssertUtil.Str.isEmpty(data.getSentence(), Tagging2100.CODE_2100);
        AssertUtil.objIsNull(data.getClassificationId(), Tagging2100.CODE_2101);
        AssertUtil.List.isEmpty(data.getTaggings(), Tagging2100.CODE_2102);
        List<KeywordsEntity> list = data.getTaggings().stream()
                .map(k -> BeanUtil.toBean(k, KeywordsEntity.class))
                .filter(taggingItem -> StrUtil.isNotBlank(taggingItem.getTagging())).toList();
        AssertUtil.List.isEmpty(list, Tagging2100.CODE_2103);
        sentenceMapper.insert(data);
        return null;
    }

    @Override
    public PageUtil.PageVO<SentenceVO> list(PageUtil.PageDTO<SentenceDTO> data) {
        return PageUtil.findPage(data,  (page) -> sentenceMapper.findAll(page,data.getData()));
    }

    @Override
    public SentenceVO del(SentenceDTO data) {
        AssertUtil.objIsNull(data.getId(), Tagging2100.CODE_2104);
        sentenceMapper.deleteById(data);
        return null;
    }

    @Override
    public SentenceVO edit(SentenceDTO data) {
        AssertUtil.objIsNull(data.getId(), Tagging2100.CODE_2104);
        AssertUtil.Str.isEmpty(data.getSentence(), Tagging2100.CODE_2100);
        AssertUtil.objIsNull(data.getClassificationId(), Tagging2100.CODE_2101);
        AssertUtil.List.isEmpty(data.getTaggings(), Tagging2100.CODE_2102);
        List<KeywordsEntity> list = data.getTaggings().stream()
                .map(k ->  BeanUtil.toBean(k, KeywordsEntity.class))
                .filter(taggingItem -> StrUtil.isNotBlank(taggingItem.getTagging())).toList();
        AssertUtil.List.isEmpty(list, Tagging2100.CODE_2103);
        sentenceMapper.updateById(data);
        return null;
    }

    @Transactional
    @Override
    public void updateByClssKeywordObjBatch(ClassificationVO classificationVO) {
        ObjectMapper mapper = new ObjectMapper();
        List<SentenceEntity> sentenceEntities = sentenceMapper.findByClassId(classificationVO);
        List<SentenceEntity> list = sentenceEntities.stream().peek(i -> {
            Map<Integer, KeywordsEntity> map1 = i.getTaggings().stream()
                    .map(k -> mapper.convertValue(k, KeywordsEntity.class))
                    .collect(Collectors.toMap(KeywordsEntity::getId, obj -> obj));
            Map<Integer, KeywordsEntity> map2 = classificationVO.getKeywords().stream()
                    .collect(Collectors.toMap(KeywordsEntity::getId, obj -> obj));
            // 返回 map1 中有 map2中没有的数据 要进行删除
            Collection<Integer> subtract = CollUtil.subtract(map1.keySet(), map2.keySet());
            // 解决 交集数据 和 map2 多出来的数据
            map2.forEach((key, value) -> {
                if (map1.containsKey(key)) {
                    KeywordsEntity item = map1.get(key);
                    value.setTagging(item.getTagging());
                    BeanUtil.copyProperties(value, item);
                    return;
                }
                map1.put(key,value);
            });
            map1.keySet().removeIf(subtract::contains);
            i.setTaggings(map1.values().stream().map(obj -> (Object)obj).toList());
        }).toList();
        saveOrUpdateBatch(list);
    }

    @Override
    public List<SentenceVO> findByIds(List<Integer> id) {
        return sentenceMapper.findByClassIds(id);
    }

    @Override
    public void updateBatch(List<SentenceVO> list) {
        sentenceMapper.updateBatch(list);
    }

}
